package cn.edu.sgu.www.mhxysy.service.baoshi.impl;

import cn.edu.sgu.www.mhxysy.dto.baoshi.BaoshiDTO;
import cn.edu.sgu.www.mhxysy.dto.baoshi.EquipmentBaoshiDTO;
import cn.edu.sgu.www.mhxysy.entity.baoshi.Baoshi;
import cn.edu.sgu.www.mhxysy.entity.baoshi.EquipmentBaoshi;
import cn.edu.sgu.www.mhxysy.entity.baoshi.EquipmentBaoshiGrade;
import cn.edu.sgu.www.mhxysy.entity.baoshi.EquipmentViewBaoshi;
import cn.edu.sgu.www.mhxysy.entity.equipment.Equipment;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentCategory;
import cn.edu.sgu.www.mhxysy.enums.InlayStatus;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.mapper.baoshi.BaoshiMapper;
import cn.edu.sgu.www.mhxysy.mapper.baoshi.EquipmentBaoshiGradeMapper;
import cn.edu.sgu.www.mhxysy.mapper.baoshi.EquipmentBaoshiMapper;
import cn.edu.sgu.www.mhxysy.mapper.baoshi.EquipmentViewBaoshiMapper;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentMapper;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentTypeMapper;
import cn.edu.sgu.www.mhxysy.pager.Pager;
import cn.edu.sgu.www.mhxysy.pager.baoshi.BaoshiPager;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.baoshi.BaoshiService;
import cn.edu.sgu.www.mhxysy.util.StringUtils;
import cn.edu.sgu.www.mhxysy.vo.baoshi.BaoshiVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Service
public class BaoshiServiceImpl implements BaoshiService {

	private final BaoshiMapper baoshiMapper;
	private final EquipmentMapper equipmentMapper;
	private final EquipmentTypeMapper equipmentTypeMapper;
	private final EquipmentBaoshiMapper equipmentBaoshiMapper;
	private final EquipmentCategoryMapper equipmentCategoryMapper;
	private final EquipmentViewBaoshiMapper equipmentViewBaoshiMapper;
	private final EquipmentBaoshiGradeMapper equipmentBaoshiGradeMapper;

	@Autowired
	public BaoshiServiceImpl(
			BaoshiMapper baoshiMapper,
			EquipmentMapper equipmentMapper,
			EquipmentTypeMapper equipmentTypeMapper,
			EquipmentBaoshiMapper equipmentBaoshiMapper,
			EquipmentCategoryMapper equipmentCategoryMapper,
			EquipmentViewBaoshiMapper equipmentViewBaoshiMapper,
			EquipmentBaoshiGradeMapper equipmentBaoshiGradeMapper) {
		this.baoshiMapper = baoshiMapper;
		this.equipmentMapper = equipmentMapper;
		this.equipmentTypeMapper = equipmentTypeMapper;
		this.equipmentBaoshiMapper = equipmentBaoshiMapper;
		this.equipmentCategoryMapper = equipmentCategoryMapper;
		this.equipmentViewBaoshiMapper = equipmentViewBaoshiMapper;
		this.equipmentBaoshiGradeMapper = equipmentBaoshiGradeMapper;
	}

	@Override
	public void inlay(EquipmentBaoshiDTO equipmentBaoshiDTO) {
		String baoshiId = equipmentBaoshiDTO.getBaoshiId();
		String equipmentId = equipmentBaoshiDTO.getEquipmentId();

		Integer location = equipmentBaoshiDTO.getLocation();
		Integer inlayStatus = equipmentBaoshiDTO.getInlayStatus();

		// 查询宝石信息
		Baoshi baoshi = baoshiMapper.selectById(baoshiId);

		// 对比镶嵌状态
		if (!inlayStatus.equals(baoshi.getInlayStatus())) {
			throw new GlobalException(ResponseCode.CONFLICT, "宝石的状态已经更新，请刷新页面后重新操作！");
		}

		/*
		 * 当前宝石状态为0-未镶嵌，操作为【镶嵌】
		 */
		if (InlayStatus.WXQ.getValue().equals(inlayStatus)) {
			Equipment equipment = equipmentMapper.selectById(equipmentId);

			validateGrade(baoshi.getGrade(), equipment.getCategoryId());
			validateInlay(baoshi.getCategoryId(), equipment.getCategoryId());

			/*
			 * 检查已镶嵌的宝石数量，最多镶嵌两颗宝石
			 */
			// 获取装备镶嵌的宝石数量
			QueryWrapper<EquipmentBaoshi> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("equipment_id", equipmentId);

			Long count = equipmentBaoshiMapper.selectCount(queryWrapper);

			// 若已经镶嵌了两颗宝石，返回错误提示
			if (count >= 2) {
				throw new GlobalException(ResponseCode.BAD_REQUEST, "镶嵌失败，此装备已经镶嵌了两颗宝石！");
			}

			// 修改宝石镶嵌状态
			UpdateWrapper<Baoshi> updateWrapper = new UpdateWrapper<>();

			updateWrapper.eq("id", baoshiId);
			updateWrapper.eq("inlay_status", InlayStatus.WXQ.getValue());

			updateWrapper.set("inlay_status", InlayStatus.YXQ.getValue());

			int update = baoshiMapper.update(updateWrapper.getEntity(), updateWrapper);

			if (update < 1) {
				throw new GlobalException(ResponseCode.CONFLICT, "宝石状态更新失败，请刷新页面后重试！");
			}

			// 添加装备宝石
			EquipmentBaoshi equipmentBaoshi = new EquipmentBaoshi();

			equipmentBaoshi.setId(null);
			equipmentBaoshi.setLocation(location);
			equipmentBaoshi.setBaoshiId(baoshiId);
			equipmentBaoshi.setEquipmentId(equipmentId);

			equipmentBaoshiMapper.insert(equipmentBaoshi);
		} else if (InlayStatus.YXQ.getValue().equals(inlayStatus)) {
			/*
			 * 当前宝石状态为1-已镶嵌，操作为【取下】
			 * 修改宝石的镶嵌状态为：0-未镶嵌
			 */
			UpdateWrapper<Baoshi> updateWrapper = new UpdateWrapper<>();

			updateWrapper.eq("id", baoshiId);
			updateWrapper.eq("inlay_status", InlayStatus.YXQ.getValue());

			updateWrapper.set("inlay_status", InlayStatus.WXQ.getValue());

			int update = baoshiMapper.update(updateWrapper.getEntity(), updateWrapper);

			if (update < 1) {
				throw new GlobalException(ResponseCode.CONFLICT, "宝石状态更新失败，请刷新页面后重试！");
			}

			// 删除装备宝石
			QueryWrapper<EquipmentBaoshi> queryWrapper = new QueryWrapper<>();

			queryWrapper.eq("equipment_id", equipmentId);
			queryWrapper.eq("location", location);
			queryWrapper.eq("baoshi_id", baoshiId);

			equipmentBaoshiMapper.delete(queryWrapper);
		} else {
			throw new GlobalException(ResponseCode.CONFLICT, "非法的镶嵌状态：" + inlayStatus);
		}
	}

	@Override
	public void insert(BaoshiDTO baoshiDTO) {
		Baoshi baoshi = toEntity(baoshiDTO);

		baoshi.setId(baoshi.uuid());
		baoshi.setInlayStatus(InlayStatus.WXQ.getValue());

		baoshiMapper.insert(baoshi);
	}

	@Override
	public void deleteById(String id) {
		baoshiMapper.deleteById(id);
	}

	@Override
	public void updateById(BaoshiDTO baoshiDTO) {
		Baoshi baoshi = toEntity(baoshiDTO);

		baoshiMapper.updateById(baoshi);
	}

	@Override
	public Baoshi selectById(String id) {
		return baoshiMapper.selectById(id);
	}

	@Override
	public Page<Baoshi> selectByPage(BaoshiPager pager) {
		QueryWrapper<Baoshi> queryWrapper = new QueryWrapper<>();
		Page<Baoshi> page = Pager.ofPage(pager);

		queryWrapper.eq(
				StringUtils.isNotEmpty(pager.getRoleId()),
				"role_id", pager.getRoleId()
		);
		queryWrapper.eq(
				pager.getCategoryId() != null,
				"category_id", pager.getCategoryId()
		);

		String statement = Pager.getOrderByStatement(pager);

		queryWrapper.last(StringUtils.isNotEmpty(statement), statement);

		return baoshiMapper.selectPage(page, queryWrapper);
	}

	@Override
	public List<BaoshiVO> selectDetails(String equipmentId) {
		return baoshiMapper.selectDetails(equipmentId);
	}

	@Override
	public List<BaoshiVO> selectByEquipmentId(String equipmentId) {
		return baoshiMapper.selectAttributes(equipmentId);
	}

	@Override
	public List<BaoshiVO> selectList(String roleId, String equipmentId) {
		if (StringUtils.isNotEmpty(roleId) && StringUtils.isNotEmpty(equipmentId)) {
			Equipment equipment = equipmentMapper.selectById(equipmentId);
			Integer topType = equipmentTypeMapper.selectTopType(equipment.getCategoryId());

			return baoshiMapper.select(topType, roleId);
		}

		return new ArrayList<>();
	}

	private Baoshi toEntity(BaoshiDTO baoshiDTO) {
		Baoshi baoshi = new Baoshi();

		baoshi.setId(baoshiDTO.getId());
		baoshi.setGrade(baoshiDTO.getGrade());
		baoshi.setRoleId(baoshiDTO.getRoleId());
		baoshi.setCategoryId(baoshiDTO.getCategoryId());

		return baoshi;
	}

	/**
	 * 验证宝石等级和装备等级是否匹配
	 * @param grade 宝石等级
	 * @param equipmentId 装备类型ID
	 */
	private void validateGrade(Integer grade, Integer equipmentId) {
		EquipmentCategory equipmentCategory = equipmentCategoryMapper.selectById(equipmentId);

		// 查询装备可镶嵌的的最大宝石等级
		QueryWrapper<EquipmentBaoshiGrade> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq("equipment_grade", equipmentCategory.getGrade());

		EquipmentBaoshiGrade equipmentBaoshiGrade = equipmentBaoshiGradeMapper.selectOne(queryWrapper);

		if (equipmentBaoshiGrade != null) {
			if (grade > equipmentBaoshiGrade.getBaoshiGrade()) {
				String message = "操作失败，选择的宝石等级超过了当前装备可镶嵌宝石的最大等级：" + equipmentBaoshiGrade.getBaoshiGrade();

				throw new GlobalException(ResponseCode.FORBIDDEN, message);
			}
		} else {
			// 添加宝石时直接抛出异常，终止添加操作
			throw new GlobalException(ResponseCode.FORBIDDEN, "该装备无法镶嵌宝石");
		}
	}

	/**
	 * 验证宝石和装备是否匹配
	 * @param baoshiId 宝石类型ID
	 * @param equipmentId 装备类型ID
	 */
	private void validateInlay(Integer baoshiId, Integer equipmentId) {
		Integer topType = equipmentTypeMapper.selectTopType(equipmentId);

		QueryWrapper<EquipmentViewBaoshi> queryWrapper = new QueryWrapper<>();

		queryWrapper.eq("baoshi_id", baoshiId);
		queryWrapper.eq("equipment_id", topType);

		Long count = equipmentViewBaoshiMapper.selectCount(queryWrapper);

		if (count == 0) {
			throw new GlobalException(ResponseCode.FORBIDDEN, "此装备无法镶嵌该类型的宝石。");
		}
	}

}